package club.jdiy.core.convert;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class StringConverter extends Converter{
    private final String source;

    public StringConverter(String source) {
        this.source = source;
    }

    @Override
    public String getSource() {
        return source;
    }

    @Override
    public Boolean getBoolean() {
        String s = source.trim();
        return !"".equals(s)
                && !"false".equalsIgnoreCase(s)
                && !"0".equalsIgnoreCase(s)
                && !"null".equalsIgnoreCase(s)
                && !"no".equalsIgnoreCase(s)
                && !"off".equalsIgnoreCase(s)
                && !"undefined".equalsIgnoreCase(s)
                && !"否".equalsIgnoreCase(s);
    }

    //off no false fail
    public Byte getByte(){
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("(\\d+)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1");
        try {
            return Byte.parseByte(str);
        } catch (NumberFormatException e) {
            throw __throw(Byte.class);
        }
    }

    public Short getShort(){
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("(\\d+)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1");
        try {
            return Short.parseShort(str);
        } catch (NumberFormatException e) {
            throw __throw(Short.class);
        }
    }

    public Integer getInteger(){
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("(\\d+)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1");
        try {
            return Integer.parseInt(str);
        } catch (NumberFormatException e) {
            throw __throw(Integer.class);
        }
    }

    public Long getLong() {
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("(\\d+)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1");
        try {
            return Long.parseLong(str);
        } catch (NumberFormatException e) {
            throw __throw(Long.class);
        }
    }

    public Float getFloat() {
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("^(\\d+)(\\.*)(\\d*)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1$2$3");
        try {
            return Float.parseFloat(str);
        } catch (NumberFormatException e) {
            throw __throw(Float.class);
        }
    }

    public Double getDouble() {
        if ("".equals(source)) return null;
        Pattern pattern = Pattern.compile("^(\\d+)(\\.*)(\\d*)(.|\r|\n)*$");
        Matcher matcher = pattern.matcher(source);
        String str = matcher.replaceAll("$1$2$3");
        try {
            return Double.parseDouble(str);
        } catch (NumberFormatException e) {
            throw __throw(Double.class);
        }
    }

    public Date getDate() {
        if ("".equals(source)) return null;
        return Date.from(getLocalDateTime().toInstant(ZoneOffset.ofHours(8)));
    }

    public LocalDate getLocalDate() {
        return getLocalDateTime().toLocalDate();
    }

    public LocalDateTime getLocalDateTime() {
        if ("".equals(source)) return null;
        try {
            if (Pattern.compile("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}(:\\d{1,2})?$").matcher(source).matches()) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-M[M]-d[d]' 'H[H]:m[m][:s[s]]"));
            } else if (Pattern.compile("^\\d{4}-\\d{1,2}-\\d{1,2}").matcher(source).matches()) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-M[M]-d[d]")).atStartOfDay();
            } else if (Pattern.compile("^\\d{4}年\\d{1,2}月\\d{1,2}日 \\d{1,2}:\\d{1,2}(:\\d{1,2})?$").matcher(source).matches()) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy年M[M]月d[d]日' 'H[H]:m[m][:s[s]]"));
            } else if (Pattern.compile("^\\d{4}年\\d{1,2}月\\d{1,2}日$").matcher(source).matches()) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy年M[M]月d[d]日")).atStartOfDay();
            } else if (Pattern.compile("^\\d{4}/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2}(:\\d{1,2})?$").matcher(source).matches()) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy/M[M]/d[d]' 'H[H]:m[m][:s[s]]"));
            } else if (Pattern.compile("^\\d{4}/\\d{1,2}/\\d{1,2}$").matcher(source).matches()) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy/M[M]/d[d]")).atStartOfDay();
            } else {
                throw __throw(Date.class);
            }
        } catch (Exception e) {
            throw __throw(Date.class);
        }
    }


    @Override
    public BigDecimal getBigDecimal() {
        try {
            return new BigDecimal(source);
        } catch (Exception e) {
            throw __throw(BigDecimal.class);
        }
    }

    @Override
    public BigInteger getBigInteger() {
        try {
            return new BigInteger(source);
        } catch (Exception e) {
            throw __throw(BigInteger.class);
        }
    }

}
